package com.transpot.service.impl.order;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.transpot.entry.driver.Driver;
import com.transpot.entry.order.*;
import com.transpot.mapper.driver.DriverMapper;
import com.transpot.mapper.order.*;
import com.transpot.service.order.OrderService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

/**
 * 订单整合类service层实现类
 */
@Service
public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements OrderService {
    @Autowired
    private OrderBaseMapper orderBaseMapper;
    @Autowired
    private OrderFeeMapper orderFeeMapper;
    @Autowired
    private OrderGoodsMapper orderGoodsMapper;
    @Autowired
    private GoodsMapper goodsMapper;
    @Autowired
    private OrderMapper orderMapper;
    @Autowired
    private AgreementMapper agreementMapper;
    @Autowired
    private DriverMapper driverMapper;
    /**
     * 添加订单的方法
     * @param orderDTO
     */
    @Override
    public void addOrder(OrderDTO orderDTO) {
        //创建订单基本信息对象
        OrderBase orderBase = new OrderBase();
        //把dto中的订单基本信息复制到该对象中
        BeanUtils.copyProperties(orderDTO, orderBase);
        //判断是否需要上门提货
        if (orderBase.getIsCollect() != null && "true".equals(orderBase.getIsCollect())) {
            orderBase.setIsCollect("需要上门提货");
        } else {
            orderBase.setIsCollect("不需要上门提货");
        }
        //把该对象插入数据库
        orderBaseMapper.insert(orderBase);
        //创建订单费用对象
        OrderFee orderFee = new OrderFee();
        //把dto中的订单费用信息复制到该对象中
        BeanUtils.copyProperties(orderDTO, orderFee);
        //把该对象插入到数据库
        orderFeeMapper.insert(orderFee);
        //遍历该订单所有货品信息对象
        for (int i = 0; i < orderDTO.getProductData().size(); i ++) {
            //拿到货品信息
            OrderGoods orderGoods = orderDTO.getProductData().get(i);
            //把货品信息插入数据库
            orderGoodsMapper.insert(orderGoods);
            //创建货品信息和订单的中间表对象
            Goods goods = new Goods();
            //设置订单主键
            goods.setGoodsId(orderGoods.getId());
            //设置货品基本信息主键
            goods.setBaseId(orderBase.getId());
            //把中间表对象插入到数据库中
            goodsMapper.insert(goods);
        }
        //创建订单信息整合对象
        Order order = new Order();
        //设置订单基本信息主键
        order.setBaseId(orderBase.getId());
        //设置订单费用信息主键
        order.setFeeId(orderFee.getId());
        //如果创建订单时指定了司机
        if (orderDTO.getDriver() != null) {
            //设置司机信息
            order.setDriverId(orderDTO.getDriver());
            //设置状态为已分配
            order.setStatus(1);
        } else {
            //否则设置状态为未分配
            order.setStatus(0);
        }
        //如果分配了车辆则设置上车辆主键
        if (orderDTO.getCar() != null) {
            order.setCarId(orderDTO.getCar());
        }
        //把订单整合对象插入数据库
        orderMapper.insert(order);
    }

    /**
     * 获取全部未分配司机的订单的方法实现
     * @param current
     * @param size
     * @return
     */
    @Override
    public Page<OrderBase> getAllOrder(int current, int size) {
        //创建Order表的分页查询对象
        IPage<Order> orderIPage = new Page<>(current, size);
        //创建Order表的条件查询对象
        LambdaQueryWrapper<Order> orderLambdaQueryWrapper = new LambdaQueryWrapper<>();
        //设置查询条件为订单状态为待分配且司机主键为空
        orderLambdaQueryWrapper.eq(Order::getStatus, 0).isNull(Order::getDriverId);
        //执行查询
        orderMapper.selectPage(orderIPage, orderLambdaQueryWrapper);
        //创建一个订单基本信息列表用来封装订单的所有基本信息
        List<OrderBase> orderBaseList = new ArrayList<>();
        //遍历查到的订单整合类数据
        for (int i = 0; i < orderIPage.getRecords().size(); i ++) {
            //根据订单整合类里的订单基本信息主键查询
            OrderBase orderBase = orderBaseMapper.selectById(orderIPage.getRecords().get(i).getBaseId());
            //把查询到的结果存到列表中
            orderBaseList.add(orderBase);
        }
        //新建一个订单基本信息对象的分页对象
        Page<OrderBase> orderBasePage = new Page<>(orderIPage.getCurrent(), orderIPage.getSize());
        //设置数据
        orderBasePage.setRecords(orderBaseList);
        //设置查询总数
        orderBasePage.setTotal(orderIPage.getTotal());
        //返回数据
        return orderBasePage;
    }

    /**
     * 根据登录账号的司机获取待接订单的方法实现
     * @param current
     * @param size
     * @param id
     * @return
     */
    @Override
    public Page<OrderBase> getOrderById(int current, int size, Integer id, int status) {
        //创建Order表的分页查询对象
        IPage<Order> orderIPage = new Page<>(current, size);
        //创建Order表的条件查询对象
        LambdaQueryWrapper<Order> orderLambdaQueryWrapper = new LambdaQueryWrapper<>();
        //设置查询条件为订单状态为已分配且司机主键为当前登录账号角色
        orderLambdaQueryWrapper.eq(Order::getStatus, status).eq(Order::getDriverId, id);
        //执行查询
        orderMapper.selectPage(orderIPage, orderLambdaQueryWrapper);
        //创建一个订单基本信息列表用来封装订单的所有基本信息
        List<OrderBase> orderBaseList = new ArrayList<>();
        //遍历查到的订单整合类数据
        for (int i = 0; i < orderIPage.getRecords().size(); i ++) {
            //根据订单整合类里的订单基本信息主键查询
            OrderBase orderBase = orderBaseMapper.selectById(orderIPage.getRecords().get(i).getBaseId());
            //把查询到的结果存到列表中
            orderBaseList.add(orderBase);
        }
        //新建一个订单基本信息对象的分页对象
        Page<OrderBase> orderBasePage = new Page<>(orderIPage.getCurrent(), orderIPage.getSize());
        //设置数据
        orderBasePage.setRecords(orderBaseList);
        //设置查询总数
        orderBasePage.setTotal(orderIPage.getTotal());
        //返回数据
        return orderBasePage;
    }

    /**
     * 获得订单信息的计数方法实现
     * @return
     */
    @Override
    public CountVO getCount() {
        //创建返回给前端的计数对象
        CountVO countVO = new CountVO();
        //创建订单整合类的条件查询对象
        LambdaQueryWrapper<Order> orderLambdaQueryWrapper = new LambdaQueryWrapper<>();
        //不设置任何条件即查询全部订单数
        Long total = orderMapper.selectCount(orderLambdaQueryWrapper);
        //设置查询条件为状态为待分配的订单
        orderLambdaQueryWrapper.eq(Order::getStatus, 0);
        //执行计数查询
        Long dealTotal = orderMapper.selectCount(orderLambdaQueryWrapper);
        //清空条件
        orderLambdaQueryWrapper.clear();
        //下面的语句完全同理上边
        orderLambdaQueryWrapper.eq(Order::getStatus, 1);
        Long assignedTotal = orderMapper.selectCount(orderLambdaQueryWrapper);
        orderLambdaQueryWrapper.clear();
        orderLambdaQueryWrapper.eq(Order::getStatus, 2);
        Long shippingTotal = orderMapper.selectCount(orderLambdaQueryWrapper);
        orderLambdaQueryWrapper.clear();
        orderLambdaQueryWrapper.eq(Order::getStatus, 3);
        Long finishTotal = orderMapper.selectCount(orderLambdaQueryWrapper);
        //把查到的数据设置到计数变量中
        countVO.setTotal(Math.toIntExact(total));
        countVO.setDealTotal(Math.toIntExact(dealTotal));
        countVO.setAssignedTotal(Math.toIntExact(assignedTotal));
        countVO.setShippingTotal(Math.toIntExact(shippingTotal));
        countVO.setFinishTotal(Math.toIntExact(finishTotal));
        return countVO;
    }

    /**
     * 给订单分配司机的方法实现
     * @param divideDTO
     */
    @Override
    public void divideDriver(DivideDTO divideDTO) {
        //创建Order表的条件查询对象
        LambdaQueryWrapper<Order> orderLambdaQueryWrapper = new LambdaQueryWrapper<>();
        //设置查询条件为与baseId一致
        orderLambdaQueryWrapper.eq(Order::getBaseId, divideDTO.getBaseId());
        //执行查询
        Order order = orderMapper.selectOne(orderLambdaQueryWrapper);
        if (order != null) {
            //如果设置了司机
            if (divideDTO.getDriver() != null) {
                //设置司机主键
                order.setDriverId(divideDTO.getDriver());
                //如果设置了车辆主键
                if (divideDTO.getCar() != null) {
                    order.setCarId(divideDTO.getCar());
                }
            }
            //设置状态为已分配
            order.setStatus(1);
        }
        //执行修改
        orderMapper.update(order, orderLambdaQueryWrapper);
    }

    /**
     * 根据订单主键删除订单的所有信息
     * @param id
     */
    @Override
    public void deleteOrderById(Integer id) {
        //创建订单整合类条件查询对象
        LambdaQueryWrapper<Order> orderLambdaQueryWrapper = new LambdaQueryWrapper<>();
        //设置查询条件为与基本信息主键一致
        orderLambdaQueryWrapper.eq(Order::getBaseId, id);
        //执行查询
        Order order = orderMapper.selectOne(orderLambdaQueryWrapper);
        //删除订单费用信息
        orderFeeMapper.deleteById(order.getFeeId());
        //删除订单基本信息
        orderBaseMapper.deleteById(order.getBaseId());
        //创建订单货物整合对象的条件查询对象
        LambdaQueryWrapper<Goods> goodsLambdaQueryWrapper = new LambdaQueryWrapper<>();
        //设置查询条件为与订单基本信息主键一致
        goodsLambdaQueryWrapper.eq(Goods::getBaseId, id);
        //执行查询
        List<Goods> goodsList = goodsMapper.selectList(goodsLambdaQueryWrapper);
        //遍历所有的查询
        for (Goods goods : goodsList) {
            //获取货物主键删除货物
            orderGoodsMapper.deleteById(goods.getGoodsId());
        }
        //删除订单货物整合对象
        goodsMapper.delete(goodsLambdaQueryWrapper);
        //删除订单整合对象
        orderMapper.delete(orderLambdaQueryWrapper);
    }

    /**
     * 根据订单id获取订单详细信息的方法实现
     * @param id
     * @return
     */
    @Override
    public OrderDTO getOrderInfoById(Integer id) {
        //创建订单整合类条件查询对象
        LambdaQueryWrapper<Order> orderLambdaQueryWrapper = new LambdaQueryWrapper<>();
        //设置查询条件为与订单基本信息主键相同
        orderLambdaQueryWrapper.eq(Order::getBaseId, id);
        //执行查询
        Order order = orderMapper.selectOne(orderLambdaQueryWrapper);
        //创建返回结果对象
        OrderDTO orderDTO = new OrderDTO();
        //查询订单的基本信息
        OrderBase orderBase = orderBaseMapper.selectById(id);
        //根据合同id查出合同名
        Agreement agreement = agreementMapper.selectById(orderBase.getShipperContractSubject());
        orderBase.setShipperContractSubject(agreement.getTitle());
        //把基本信息数据赋值到返回结果对象中
        BeanUtils.copyProperties(orderBase, orderDTO);
        //查询订单费用信息
        OrderFee orderFee = orderFeeMapper.selectById(order.getFeeId());
        //把费用信息数据赋值到返回结果对象中
        BeanUtils.copyProperties(orderFee, orderDTO);
        //创建货品整合类对象
        LambdaQueryWrapper<Goods> goodsLambdaQueryWrapper = new LambdaQueryWrapper<>();
        //设置查询条件为与订单基本信息主键一致
        goodsLambdaQueryWrapper.eq(Goods::getBaseId, id);
        //执行查询
        List<Goods> goodsList = goodsMapper.selectList(goodsLambdaQueryWrapper);
        //创建货物基本信息列表
        List<OrderGoods> orderGoodsList = new ArrayList<>();
        //遍历所有的查询
        for (Goods goods : goodsList) {
            //获取货物主键查询货物信息
            OrderGoods orderGoods = orderGoodsMapper.selectById(goods.getGoodsId());
            orderGoodsList.add(orderGoods);
        }
        //把货品信息存到返回结果对象中
        orderDTO.setProductData(orderGoodsList);
        //重新设置订单id
        orderDTO.setId(id);
        return orderDTO;
    }

    /**
     * 根据订单id修改订单信息
     * @param orderDTO
     */
    @Override
    public void updateOrderById(OrderDTO orderDTO) {
        //删除订单基本信息的实现
        //创建订单整合类条件查询对象
        LambdaQueryWrapper<Order> orderLambdaQueryWrapper = new LambdaQueryWrapper<>();
        //设置查询条件为与基本信息主键一致
        orderLambdaQueryWrapper.eq(Order::getBaseId, orderDTO.getId());
        //执行查询
        Order order = orderMapper.selectOne(orderLambdaQueryWrapper);
        //创建订单货物整合对象的条件查询对象
        LambdaQueryWrapper<Goods> goodsLambdaQueryWrapper = new LambdaQueryWrapper<>();
        //设置查询条件为与订单基本信息主键一致
        goodsLambdaQueryWrapper.eq(Goods::getBaseId, orderDTO.getId());
        //执行查询
        List<Goods> goodsList = goodsMapper.selectList(goodsLambdaQueryWrapper);
        //遍历所有的查询
        for (Goods goods : goodsList) {
            //获取货物主键删除货物
            orderGoodsMapper.deleteById(goods.getGoodsId());
        }
        //删除订单货物整合对象
        goodsMapper.delete(goodsLambdaQueryWrapper);

        //创建订单基本信息的条件查询对象
        LambdaQueryWrapper<OrderBase> orderBaseLambdaQueryWrapper = new LambdaQueryWrapper<>();
        //根据主键查询订单基本信息对象
        OrderBase oldOrderBase = orderBaseMapper.selectById(order.getBaseId());
        //创建订单基本信息对象
        OrderBase orderBase = new OrderBase();
        //把dto中的订单基本信息复制到该对象中
        BeanUtils.copyProperties(orderDTO, orderBase);
        //设置主键为原来的订单信息对象
        orderBase.setId(oldOrderBase.getId());
        //把订单基本信息根据主键修改
        orderBaseMapper.updateById(orderBase);

        //创建订单费用信息的条件查询对象
        LambdaQueryWrapper<OrderFee> orderFeeLambdaQueryWrapper = new LambdaQueryWrapper<>();
        //根据主键查询订单费用信息对象
        OrderFee oldOrderFee = orderFeeMapper.selectById(order.getFeeId());
        //创建订单费用对象
        OrderFee orderFee = new OrderFee();
        //把dto中的订单费用信息复制到该对象中
        BeanUtils.copyProperties(orderDTO, orderFee);
        //把主键设置为原来的订单费用信息
        orderFee.setId(oldOrderFee.getId());
        //根据主键修改费用信息
        orderFeeMapper.updateById(orderFee);
        //遍历该订单所有货品信息对象
        for (int i = 0; i < orderDTO.getProductData().size(); i ++) {
            //拿到货品信息
            OrderGoods orderGoods = orderDTO.getProductData().get(i);
            //把货品信息插入数据库
            orderGoodsMapper.insert(orderGoods);
            //创建货品信息和订单的中间表对象
            Goods goods = new Goods();
            //设置订单主键
            goods.setGoodsId(orderGoods.getId());
            //设置货品基本信息主键
            goods.setBaseId(orderBase.getId());
            //把中间表对象插入到数据库中
            goodsMapper.insert(goods);
        }
    }

    /**
     * 获取已分配司机订单方法的实现
     * @param current
     * @param size
     * @return
     */
    @Override
    public Page<OrderDriverVO> getAllOrderIsAssigned(int current, int size) {
        //创建订单整合类的分页对象
        Page<Order> orderPage = new Page<>(current, size);
        //创建订单整合类的条件查询对象
        LambdaQueryWrapper<Order> orderLambdaQueryWrapper = new LambdaQueryWrapper<>();
        //设置查询条件为订单状态是1，即已分配
        orderLambdaQueryWrapper.eq(Order::getStatus, 1);
        //执行分页查询
        orderMapper.selectPage(orderPage, orderLambdaQueryWrapper);
        //设置订单基础信息和司机信息对象列表用来存查到的订单基础信息
        List<OrderDriverVO> orderDriverVOList = new ArrayList<>();
        //遍历查到的所有订单整合类
        for (int i = 0; i < orderPage.getRecords().size(); i ++) {
            //获得订单整合类里的订单基础信息主键
            Integer baseId = orderPage.getRecords().get(i).getBaseId();
            //根据主键查询订单的基础信息
            OrderBase orderBase = orderBaseMapper.selectById(baseId);
            //创建订单司机信息对象
            OrderDriverVO orderDriverVO = new OrderDriverVO();
            //把订单基本信息存储结果对象中
            BeanUtils.copyProperties(orderBase, orderDriverVO);
            //获得订单类里的司机主键
            Integer driverId = orderPage.getRecords().get(i).getDriverId();
            //执行查询
            Driver driver = driverMapper.selectById(driverId);
            //把司机对象存到结果对象中
            BeanUtils.copyProperties(driver, orderDriverVO);
            //订单信息id会被司机的覆盖，因此重新赋值回来
            orderDriverVO.setId(orderBase.getId());
            //把对象添加到列表中
            orderDriverVOList.add(orderDriverVO);
        }
        //重新创建一个订单司机基础信息的分页对象
        Page<OrderDriverVO> orderBasePage = new Page<>(current, size);
        //设置查到的总数
        orderBasePage.setTotal(orderPage.getTotal());
        //设置查到的基础信息列表
        orderBasePage.setRecords(orderDriverVOList);
        return orderBasePage;
    }

    /**
     * 获取全部配送中订单
     * @param current
     * @param size
     * @return
     */
    @Override
    public Page<OrderDriverVO> getOrderIsShipping(int current, int size) {
        //创建订单整合类的分页对象
        Page<Order> orderPage = new Page<>(current, size);
        //创建订单整合类的条件查询对象
        LambdaQueryWrapper<Order> orderLambdaQueryWrapper = new LambdaQueryWrapper<>();
        //设置查询条件为订单状态是1，即已分配
        orderLambdaQueryWrapper.eq(Order::getStatus, 2);
        //执行分页查询
        orderMapper.selectPage(orderPage, orderLambdaQueryWrapper);
        //设置订单基础信息和司机信息对象列表用来存查到的订单基础信息
        List<OrderDriverVO> orderDriverVOList = new ArrayList<>();
        //遍历查到的所有订单整合类
        for (int i = 0; i < orderPage.getRecords().size(); i ++) {
            //获得订单整合类里的订单基础信息主键
            Integer baseId = orderPage.getRecords().get(i).getBaseId();
            //根据主键查询订单的基础信息
            OrderBase orderBase = orderBaseMapper.selectById(baseId);
            //创建订单司机信息对象
            OrderDriverVO orderDriverVO = new OrderDriverVO();
            //把订单基本信息存储结果对象中
            BeanUtils.copyProperties(orderBase, orderDriverVO);
            //获得订单类里的司机主键
            Integer driverId = orderPage.getRecords().get(i).getDriverId();
            //执行查询
            Driver driver = driverMapper.selectById(driverId);
            //把司机对象存到结果对象中
            BeanUtils.copyProperties(driver, orderDriverVO);
            //订单信息id会被司机的覆盖，因此重新赋值回来
            orderDriverVO.setId(orderBase.getId());
            //把对象添加到列表中
            orderDriverVOList.add(orderDriverVO);
        }
        //重新创建一个订单司机基础信息的分页对象
        Page<OrderDriverVO> orderBasePage = new Page<>(current, size);
        //设置查到的总数
        orderBasePage.setTotal(orderPage.getTotal());
        //设置查到的基础信息列表
        orderBasePage.setRecords(orderDriverVOList);
        return orderBasePage;
    }

    /**
     * 获取全部已完成订单
     * @param current
     * @param size
     * @return
     */
    @Override
    public Page<OrderDriverVO> getOrderIsFinished(int current, int size) {
        //创建订单整合类的分页对象
        Page<Order> orderPage = new Page<>(current, size);
        //创建订单整合类的条件查询对象
        LambdaQueryWrapper<Order> orderLambdaQueryWrapper = new LambdaQueryWrapper<>();
        //设置查询条件为订单状态是1，即已分配
        orderLambdaQueryWrapper.eq(Order::getStatus, 3);
        //执行分页查询
        orderMapper.selectPage(orderPage, orderLambdaQueryWrapper);
        //设置订单基础信息和司机信息对象列表用来存查到的订单基础信息
        List<OrderDriverVO> orderDriverVOList = new ArrayList<>();
        //遍历查到的所有订单整合类
        for (int i = 0; i < orderPage.getRecords().size(); i ++) {
            //获得订单整合类里的订单基础信息主键
            Integer baseId = orderPage.getRecords().get(i).getBaseId();
            //根据主键查询订单的基础信息
            OrderBase orderBase = orderBaseMapper.selectById(baseId);
            //创建订单司机信息对象
            OrderDriverVO orderDriverVO = new OrderDriverVO();
            //把订单基本信息存储结果对象中
            BeanUtils.copyProperties(orderBase, orderDriverVO);
            //获得订单类里的司机主键
            Integer driverId = orderPage.getRecords().get(i).getDriverId();
            //执行查询
            Driver driver = driverMapper.selectById(driverId);
            //把司机对象存到结果对象中
            if (driver != null)
                BeanUtils.copyProperties(driver, orderDriverVO);
            //订单信息id会被司机的覆盖，因此重新赋值回来
            orderDriverVO.setId(orderBase.getId());
            //把对象添加到列表中
            orderDriverVOList.add(orderDriverVO);
        }
        //重新创建一个订单司机基础信息的分页对象
        Page<OrderDriverVO> orderBasePage = new Page<>(current, size);
        //设置查到的总数
        orderBasePage.setTotal(orderPage.getTotal());
        //设置查到的基础信息列表
        orderBasePage.setRecords(orderDriverVOList);
        return orderBasePage;
    }
}
